package org.jiuling.validation.spring.handle;

import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
import org.jiuling.basics.exception.BasicsException;
import org.jiuling.basics.util.ClassUtil;
import org.jiuling.basics.validation.*;
import org.jiuling.validation.spring.annotation.MutualExclusion;
import org.jiuling.validation.spring.enums.MutualExclusionTpyeEnum;
import org.springframework.stereotype.Component;

/**
 * 互斥校验
 * @author 紫灵
 * @date 2024年10月27日 20时39分07秒
 */
@Component
public class MutualExclusionValidator implements ConstraintValidator<MutualExclusion, Object> {

    /** 主字段 */
    private String mainField;
    /** 字段 */
    private String[] fields;
    /** 互斥类型 */
    private MutualExclusionTpyeEnum type;

    @Override
    public void initialize(MutualExclusion mutualExclusion) {
        this.mainField = mutualExclusion.value();
        this.fields = mutualExclusion.fields();
        this.type = mutualExclusion.type();
    }

    @Override
    public boolean isValid(Object value, ConstraintValidatorContext constraintValidatorContext) {
        // 校验对象本身是否为空，如果为空则不进行校验
        if (ObjectVerify.isNull(value)) return true;

        // 判断字段是否为空，字段不为空则需要进行校验
        if (!ArrayVerify.isEmpty(fields)){
            // 判断互斥类型
            return switch (type){
                case COEXIST -> isValidCoexist(value);
                case NOT_COEXIST -> isValidNotCoexist(value);
                case ONLY -> isValidOnly(value);
                case NULL_OR_ONLY -> isValidNullOrOnly(value);
            };
        }
        return true;

    }

    /**
     * 空或者唯一
     * @param object 对象
     * @return 空或者唯一是否有效
     */
    private boolean isValidNullOrOnly(Object object){
        boolean previousFieldExist = false;
        for (String field : fields){
            // 字段值为空
            Boolean fieldIsNull = fieldValueIsNull(object, field);
            if (!BooleanVerify.isTrue(fieldIsNull)){
                if (previousFieldExist) return false;
                previousFieldExist = true;
            }
        }
        // 如果没有出现过非空字段，则表示所有字段都是空，返回true
        return true;
    }

    /**
     * 共存是否有效
     * @return 共存是否有效
     */
    private boolean isValidCoexist(Object object){
        // 如果主字段为空则不进行校验
        if (StringVerify.isBlank(mainField)) return true;
        // 如果主字段的值为空则不进行校验
        Boolean fieldValueIsNull = fieldValueIsNull(object, mainField);
        if (BooleanVerify.isNull(fieldValueIsNull) || BooleanVerify.isTrue(fieldValueIsNull)) return true;
        // 遍历字段列表
        for (String field : fields){
            // 字段值为空
            Boolean fieldIsNull = fieldValueIsNull(object, field);
            // 如果字段值为空表示非基础类型值，则跳过校验
            if (BooleanVerify.isNull(fieldIsNull)){
                continue;
            }
            // 当出现空值的时候则标识共存无效
            if (BooleanVerify.isTrue(fieldIsNull)) return false;
        }
        return true;
    }

    /**
     * 不共存是否有效
     * @param object 对象
     * @return 是否有效
     */
    private boolean isValidNotCoexist(Object object){
        // 初始化上一次的字段为不存在
        boolean previousFieldExist = false;
        for (String field : fields){
            // 字段值为空
            Boolean fieldIsNull = fieldValueIsNull(object, field);
            if (BooleanVerify.isTrue(fieldIsNull)){
                if (previousFieldExist) return false;
                previousFieldExist = true;
            }
        }
        return true;
    }

    /**
     * 唯一是否有效
     * @param object 对象
     * @return 是否有效
     */
    private boolean isValidOnly(Object object){
        boolean previousFieldExist = false;
        for (String field : fields){
            // 字段值为空
            Boolean fieldIsNull = fieldValueIsNull(object, field);
            if (!BooleanVerify.isTrue(fieldIsNull)){
                if (previousFieldExist) return false;
                previousFieldExist = true;
            }
        }
        return previousFieldExist;
    }

    /**
     * 字段值是否为空
     * @return 是否为空
     */
    private Boolean fieldValueIsNull(Object obj,String fieldName){
        try {
            // 获取值对象
            Object valueObject = ClassUtil.getFieldValue(obj, fieldName);
            // 基础字段值是否为空，返回空值标识该字段不为基础字段
            Boolean valueBlank = baseTypeVerifyIsBlank(valueObject);
            // 跳过非基础字段校验
            if (BooleanVerify.isNull(valueBlank)) return true;
            return valueBlank;
        } catch (BasicsException ignored) {
            // 不处理异常
        }
        return true;
    }

    private Boolean baseTypeVerifyIsBlank(Object object){
        // 不为基础对象不参与校验
        if (ObjectVerify.isBaseType(object)) {
            if (object instanceof String str) return StringVerify.isBlank(str);
            if (object instanceof Integer i) return IntegerVerify.isBlank(i);
            if (object instanceof Long l) return LongVerify.isBlank(l);
        }
        return null;
    }

}
